<template>
  <div class="rich-editor" :class="{'rich-editor-fillHeight':fillHeight,'rich-editor-hasappend':hasAppendSlot}">
    <template v-if="disabled">
      <div class="vue-rich-editor" v-html="content"></div>
    </template>
    <template v-else-if="editorInit!==null">
      <vue-editor class="rich-editor-form" ref="richEditorForm" v-model="content" :init="editorInit" model-events="change keyup undo redo"
        @input="handleInput" :toolbar="toolbar" :plugins="plugins" :disabled="readonly" :initial-value="initialValue"></vue-editor>
    </template>
    <div v-if="hasAppendSlot" style="margin-top:10px;text-align:center">
      <slot name="append" :imgFiles="imgFileList" :editor="editor"></slot>
    </div>
    <el-dialog append-to-body :title="dialogTitle" custom-class="sys-dialog" :close-on-click-modal="false" :visible.sync="openDialog" top="10vh"
      class="rich-editor-dialog" @closed="dialogClosed">
      <div style="height:calc(80vh - 54px);overflow:auto">
        <template v-if="openDialog">
          <insert-image v-if="dialogType==='outlineImage'" :query-value="queryValue" @insert-img="addImages"></insert-image>
        </template>
      </div>
    </el-dialog>
  </div>
</template>

<script>
  import SystemUtil from 'utils/systemUtil';
  import tinymce from 'tinymce/tinymce';
  import Editor from '@tinymce/tinymce-vue';
  import 'tinymce/themes/modern/theme';
  import 'tinymce/plugins/image';
  import 'tinymce/plugins/imagetools';
  import 'tinymce/plugins/lists';
  import 'tinymce/plugins/contextmenu';
  import 'tinymce/plugins/wordcount';
  import 'tinymce/plugins/colorpicker';
  import 'tinymce/plugins/textcolor';
  import 'tinymce/plugins/pagebreak';
  import 'tinymce/plugins/nonbreaking';
  import 'tinymce/plugins/charmap';
  import 'tinymce/plugins/advlist';
  import 'tinymce/plugins/searchreplace';
  import 'tinymce/plugins/template';
  import 'tinymce/plugins/insertdatetime';
  import 'tinymce/plugins/spellchecker';
  import 'tinymce/plugins/textpattern';
  import 'tinymce/plugins/lists';
  import 'tinymce/plugins/preview';

  import UploadFileApi from 'services/uploadFileApi';

  import InsertImage from './insertImage';

  export default {
    props: {
      value: {
        type: String,
        default: true
      },
      inline: {
        type: Boolean,
        default: false
      },
      height: {
        type: [Number, String],
        default: '100%'
      },
      fillHeight: {
        type: Boolean,
        default: true
      },
      plugins: {
        type: [String, Array],
        default: function () {
          return [
            'charmap',
            'advlist',
            'searchreplace',
            'colorpicker',
            'contextmenu',
            'imagetools',
            'image',
            'preview',
            'template pagebreak nonbreaking insertdatetime lists textcolor wordcount spellchecker textpattern'
          ]
        }
      },
      toolbar: {
        type: [String, Array],
        default: function () {
          return [
            'undo redo | fontselect fontsizeselect | bold italic strikethrough forecolor backcolor | alignleft aligncenter alignright alignjustify',
            'charmap | numlist bullist outdent indent | searchreplace | image outlineImage | removeformat | preview'
          ];
        }
      },
      readonly: {
        type: Boolean,
        defualt: false
      },
      disabled: {
        type: Boolean,
        defualt: false
      },
      contextmenu: {
        type: String,
        default: 'undo redo | cut copy paste | selectall'
      },
      queryValue: {
        type: String,
        default: ''
      }
    },

    computed: {
      hasAppendSlot() {
        return this.$slots.append || this.$scopedSlots.append;
      }
    },

    watch: {
      value() {
        let useInput = this.useInput;
        if (useInput !== null) {
          this.useInput = null;
          return;
        }
        this.content = this.value;
      }
    },

    data() {
      return {
        content: this.value,
        useInput: null,
        editor: null,
        editorInit: null,
        basePath: SystemUtil.getBasePath(),
        initialValue: '<div></div>',
        imgFileList: [],
        openDialog: false,
        dialogTitle: '',
        dialogType: ''
      }
    },

    created() {
      this.initEditor();
    },

    methods: {
      initEditor() {
        let sizes = [];
        for (let i = 12; i <= 50; i++) {
          sizes.push(i + 'px');
        }

        let baseUrl = '';
        if (process.env.NODE_ENV !== 'development'){
          baseUrl = SystemUtil.getProjectName();
        }

        this.editorInit = {
          language_url: `${baseUrl}/static/tinymce/langs/zh_CN.js`,
          language: 'zh_CN',
          height: this.height,
          skin_url: `${baseUrl}/static/tinymce/skins/lightgray`,
          imagetools_cors_hosts: ['qiniu.manlitech.com'],
          imagetools_toolbar: "editimage imageoptions",
          resize: false,
          contextmenu: this.contextmenu,
          branding: false,
          elementpath: false,
          inline: this.inline,
          fontsize_formats: sizes.join(" "),
          font_formats: "宋体=宋体;黑体=黑体;仿宋=仿宋;楷体=楷体;隶书=隶书;幼圆=幼圆;Arial=arial,helvetica,sans-serif;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",
          statusbar: false,
          body_class: 'vue-rich-editor',
          content_css: `${this.basePath}/static/tinymce/vueEditor.css`,
          indentation: '20px',
          automatic_uploads: true,
          image_advtab: true,
          image_title: true,
          images_upload_base_path: this.basePath,
          formats: {
            bold: {
              inline: 'span',
              styles: {
                fontWeight: 'bold'
              }
            },
            italic: {
              inline: 'span',
              styles: {
                fontStyle: 'italic'
              }
            },
          },
          menu: {
            edit: {
              title: 'Edit',
              items: 'undo redo | cut copy paste | selectall'
            },
            format: {
              title: 'Format',
              items: 'bold italic underline strikethrough | removeformat'
            },
            insert: {
              title: '插入',
              items: 'image outlineImage'
            }
          },
          setup: editor => {
            editor.addButton("outlineImage", {
              icon: 'outline-image',
              title: '媒体库',
              onclick: () => {
                this.dialogTitle = '媒体库';
                this.dialogType = 'outlineImage';
                this.openDialog = true;
              }
            });

            editor.addMenuItem('outlineImage', {
              icon: 'outline-image',
              text: '媒体库',
              context: 'tools',
              onclick: () => {
                this.dialogTitle = '媒体库';
                this.dialogType = 'outlineImage';
                this.openDialog = true;
              }
            });
          },
          init_instance_callback: editor => {
            this.editor = editor;
            this.$emit('ready', editor);

            this.$nextTick(() => {
              let $editor = $(this.$el).find('.mce-tinymce>.mce-container-body.mce-stack-layout');
              let $toolbar = $editor.find('>.mce-stack-layout-item.mce-top-part');
              let $area = $editor.find('.mce-edit-area');
              let height = $toolbar.height();
              if (height !== null) {
                $area.height(`calc(100% - ${height}px)`);
              }
              $(this.$el).find('.mce-tinymce').width('calc(100% - 2px)');
            });
          },
          images_upload_handler: (blobInfo, success, failure) => {
            let file = blobInfo.blob();
            let name = file.name;
            if (name === undefined) {
              file.name = `image_${_.random(0, 1000, false)}`;
            }
            UploadFileApi.uploadImg(file).then(imgUrl => {
              if (imgUrl === '') {
                failure('获取token失败');
              } else {
                success(imgUrl);
              }
            }).catch(error => {
              failure(error.message);
            });
          }
        };
      },

      handleInput() {
        let content = this.content;
        this.useInput = content;
        this.$emit('input', content);
        this.$emit('change', content);
      },

      addImages(imageList) {
        this.openDialog = false;
        let editor = this.editor;
        let imgDomList = [];
        for (let i = 0; i < imageList.length; i++) {
          const image = imageList[i];
          imgDomList.push(`<img src="${image.url}" width="${image.width}" height="${image.height}">`);
        }
        editor.insertContent(imgDomList.join(''));
      },

      dialogClosed() {
        this.dialogTitle = '';
        this.dialogType = '';
      },

      getEditorContent() {
        let content = this.content;
        let $imgs = $(content).find('img');
        let uploadImgs = [];
        for (let i = 0; i < $imgs.length; i++) {
          const $img = $($imgs[i]);
          let src = $img.attr('src');
          if (src.indexOf('data:') === 0) {
            uploadImgs.push({
              base64: src
            });
          }
        }

        if (uploadImgs.length === 0) {
          return Promise.resolve(content);
        }

        return UploadFileApi.uploadBase64ImgList(uploadImgs).then(uploadImgList => {
          for (let i = 0; i < uploadImgList.length; i++) {
            const uploadImg = uploadImgList[i];
            content = content.replace(uploadImg.base64, uploadImg.url);
          }
          return content;
        });
      }
    },

    components: {
      VueEditor: Editor,
      InsertImage
    }
  }

</script>
<style lang="scss">
  .rich-editor {
    height: 100%;

    .mce-tinymce .mce-container-body .mce-toolbar-grp .mce-stack-layout {
      .mce-toolbar {
        border-bottom: 1px solid #d9d9d9;

        &:last-child {
          border-bottom: none;
        }
      }
    }

    &.rich-editor-fillHeight {
      .mce-tinymce {
        height: calc(100% - 2px);

        >.mce-stack-layout {
          height: 100%;
        }
      }

      &.rich-editor-hasappend .mce-tinymce {
        height: calc(100% - 55px);
      }
    }
  }

  .vue-rich-editor {
    line-height: 1.3;
    font-size: 14px;
    font-family: Arial, Verdana, Helvetica, sans-serif;
  }

  .vue-rich-editor p,
  .vue-rich-editor ul,
  .vue-rich-editor ol {
    margin: 0;
  }

  .vue-rich-editor ul,
  .vue-rich-editor ol {
    padding-left: 1em;
  }

</style>
